package controllers

import (
	"fmt"
	"gis-server/dto"
	"gis-server/models"
	"strconv"
	"strings"
	"time"

	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/server/web"
)

type WaterloggingController struct {
	web.Controller
}

// 新增 getList 方法
func (c *WaterloggingController) GetList() {
	o := orm.NewOrm()
	tsString := c.Ctx.Input.Query("ts")
	ts := time.Now()
	if tsString != "" {
		tsI, _ := strconv.ParseInt(tsString, 10, 64)
		ts = time.Unix(tsI, 0)
	}
	var waterLevels []*models.WaterLevelData
	var predictWaterLevels []*models.WaterLevelPredict
	var historyMap = map[string]*dto.Feature{}
	_, err := o.QueryTable(new(models.WaterLevelData)).Filter("watch_time__lte", ts).OrderBy("watch_time").All(&waterLevels)
	if err != nil {
		fmt.Println("Error fetching water levels: ", err)
	}

	//todo: 这个从预测的表里取数据
	_, err = o.QueryTable(new(models.WaterLevelPredict)).
		Filter("watch_time__gte", ts).
		Filter("watch_time__lt", ts.Add(time.Minute*5)).
		OrderBy("watch_time").
		All(&predictWaterLevels)
	if err != nil {
		fmt.Println("Error fetching predict water levels: ", err)
	}

	pointMap := models.GetPointMap()
	for _, wl := range waterLevels {
		pointInfo := pointMap[wl.SiteCode]

		format(historyMap, pointInfo, wl)
		// if wl.WatchTime.Before(ts) {
		// 	format(historyMap, pointInfo, wl)
		// } else {
		// 	format(currentMap, pointInfo, wl)
		// }
	}
	for _, wl := range predictWaterLevels {
		pointInfo := pointMap[wl.SiteCode]

		formatPredict(historyMap, pointInfo, wl)

	}

	history := dto.FeatureCollection{
		Type:     "FeatureCollection",
		Features: map2slice(historyMap),
		CRS: dto.CRS{
			Type:       "name",
			Properties: dto.CRSProperties{Name: "urn:ogc:def:crs:OGC:1.3:CRS84"},
		},
	}
	// current := dto.FeatureCollection{
	// 	Type:     "FeatureCollection",
	// 	Features: map2slice(currentMap),
	// 	CRS: dto.CRS{
	// 		Type:       "name",
	// 		Properties: dto.CRSProperties{Name: "urn:ogc:def:crs:OGC:1.3:CRS84"},
	// 	},
	// }
	// future := dto.FeatureCollection{
	// 	Type:     "FeatureCollection",
	// 	Features: map2slice(futureMap),
	// 	CRS: dto.CRS{
	// 		Type:       "name",
	// 		Properties: dto.CRSProperties{Name: "urn:ogc:def:crs:OGC:1.3:CRS84"},
	// 	},
	// }
	// c.Data["json"] = map[string]interface{}{
	// 	"history": history,
	// 	"current": current,
	// 	"future":  future,
	// }
	c.Data["json"] = history

	c.ServeJSON()
}

func format(historyMap map[string]*dto.Feature, pointInfo models.PointInfo, wl *models.WaterLevelData) {
	if mapInfo, ok := historyMap[pointInfo.SiteCode]; ok {
		mapInfo.Properties.Timestamps = append(mapInfo.Properties.Timestamps, wl.WatchTime.Format("2006-01-02 15:04:05"))
		mapInfo.Properties.Depth = append(mapInfo.Properties.Depth, wl.WaterLevel)
		mapInfo.Properties.Risk = append(mapInfo.Properties.Risk, wl.FormatRisk())
	} else {
		historyMap[pointInfo.SiteCode] = &dto.Feature{
			Type: "Feature",
			ID:   pointInfo.Id,
			Geometry: dto.Geometry{
				Type:        "Point",
				Coordinates: []float64{pointInfo.Lng, pointInfo.Lat},
			},
			Properties: dto.Properties{
				Name:       pointInfo.SiteName,
				Class:      pointInfo.Level,
				District:   pointInfo.RegionalName,
				Timestamps: []string{wl.WatchTime.Format("2006-01-02 15:04:05")},
				Depth:      []float64{wl.WaterLevel},
				Risk:       []string{wl.FormatRisk()},
			},
		}
	}
}

func formatPredict(historyMap map[string]*dto.Feature, pointInfo models.PointInfo, wl *models.WaterLevelPredict) {
	waterLevels := strings.Split(wl.WaterLevel, ",")
	var ft *dto.Feature
	if mapInfo, ok := historyMap[pointInfo.SiteCode]; ok {
		ft = mapInfo
	} else {
		ft = &dto.Feature{
			Type: "Feature",
			ID:   pointInfo.Id,
			Geometry: dto.Geometry{
				Type:        "Point",
				Coordinates: []float64{pointInfo.Lng, pointInfo.Lat},
			},
			Properties: dto.Properties{
				Name:       pointInfo.SiteName,
				Class:      pointInfo.Level,
				District:   pointInfo.RegionalName,
				Timestamps: nil,
				Depth:      nil,
				Risk:       nil,
			},
		}
	}
	for i, waterLevel := range waterLevels {
		if waterLevel == "0" || waterLevel == "0.0" {
			continue
		}
		level, _ := strconv.ParseFloat(waterLevel, 64)
		ft.Properties.Timestamps = append(ft.Properties.Timestamps, wl.WatchTime.Add(time.Minute*5*time.Duration(i+1)).Format("2006-01-02 15:04:05"))
		ft.Properties.Depth = append(ft.Properties.Depth, level)
		ft.Properties.Risk = append(ft.Properties.Risk, wl.FormatRisk(level))

	}
	historyMap[pointInfo.SiteCode] = ft
}

func map2slice(m map[string]*dto.Feature) []dto.Feature {
	var res []dto.Feature
	for _, v := range m {
		res = append(res, *v)
	}
	return res
}
